package com.tuju.jetpackfirstdemo.widget;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import android.widget.FrameLayout;

public class MultiBezierView extends FrameLayout {

    private static final int LINEWIDTH = 5;
    private static final int POINTWIDTH = 10;

    private Paint mPaint;
    private Path mPath;

    private Context mContext;
    /**
     * 即将要穿越的点集合
     */
    private ArrayList<Point> mPoints;
    /**
     * 中点集合
     */
    private ArrayList<Point> mMidPoints;
    /**
     * 中点的中点集合
     */
    private ArrayList<Point> mMidMidPoints;
    /**
     * 移动后的点集合(控制点)
     */
    private ArrayList<Point> mAssistPoints;


    public MultiBezierView(Context context) {
        this(context, null);
    }

    public MultiBezierView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MultiBezierView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mContext = context;
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPath = new Path();

        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(5);
        mPaint.setDither(true);
        mPaint.setAntiAlias(true);

        getScreenParams();
        setBackgroundColor(Color.WHITE);
        getBackground().setAlpha(0);
        initPoints();
        initMidPoints();
        initMidMidPoints();
        initAssistPoints(mPoints, mMidPoints, mMidMidPoints);
    }

    private void initPoints() {
        mPoints = new ArrayList<Point>();
        int pointWidthSpace = mScreenWidth / 5;
        int pointHeightSpace = 100;

        for (int i = 0; i < 5; i++) {
            Point point;
            // 一高一低五个点
            if (i % 2 != 0) {
                point = new Point((int) (pointWidthSpace * (i + 0.5)), mScreenHeigh / 2 - pointHeightSpace);
            } else {
                point = new Point((int) (pointWidthSpace * (i + 0.5)), mScreenHeigh / 2);
            }


            mPoints.add(point);
        }

    }

    private void initMidPoints() {
        mMidPoints = new ArrayList<Point>();
        for (int i = 0; i < mPoints.size() - 1; i++) {
            Point midPoint = new Point((mPoints.get(i).x + mPoints.get(i + 1).x) / 2,
                    (mPoints.get(i).y + mPoints.get(i + 1).y) / 2);
            mMidPoints.add(midPoint);
        }
    }

    private void initMidMidPoints() {
        mMidMidPoints = new ArrayList<Point>();

        for (int i = 0; i < mMidPoints.size() - 1; i++) {
            Point midMidPoint = new Point((mMidPoints.get(i).x + mMidPoints.get(i + 1).x) / 2,
                    (mMidPoints.get(i).y + mMidPoints.get(i + 1).y) / 2);

            mMidMidPoints.add(midMidPoint);
        }
    }

    private void initAssistPoints(List<Point> points, List<Point> midPoints, List<Point> midMidPoints) {
        mAssistPoints = new ArrayList<Point>();

        for (int i = 0; i < points.size(); i++) {
            if (i == 0 || i == points.size() - 1) {
                continue;
            } else {
                Point assistBefore = new Point();
                assistBefore.x = midPoints.get(i - 1).x + (points.get(i).x - mMidMidPoints.get(i - 1).x);
                assistBefore.y = midPoints.get(i - 1).y + (points.get(i).y - mMidMidPoints.get(i - 1).y);

                Point assistAfter = new Point();
                assistAfter.x = midPoints.get(i).x + (points.get(i).x - mMidMidPoints.get(i - 1).x);
                assistAfter.y = midPoints.get(i).y + (points.get(i).y - mMidMidPoints.get(i - 1).y);
                mAssistPoints.add(assistBefore);
                mAssistPoints.add(assistAfter);
            }
        }
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画原始点
        drawPoints(canvas);
        //画原始点连接的直线
        drawLineForPoints(canvas);
        //画中点
        drawMidPoints(canvas);
        //画中点的中点即图中的P6
        drawMidMidPoints(canvas);
        //画辅助点
        drawAssistPoints(canvas);
        drawBezierPath(canvas);
    }

    private void drawPoints(Canvas canvas) {
        mPaint.setStrokeWidth(POINTWIDTH);

        for (Point point : mPoints) {
            canvas.drawPoint(point.x, point.y, mPaint);

        }
    }

    private void drawLineForPoints(Canvas canvas) {
        mPaint.setStrokeWidth(LINEWIDTH);
        mPaint.setColor(Color.RED);
        mPath.moveTo(mPoints.get(0).x, mPoints.get(0).y);
        for (int i = 1; i < mPoints.size(); i++) {

            mPath.lineTo(mPoints.get(i).x, mPoints.get(i).y);
        }
        canvas.drawPath(mPath, mPaint);
    }

    private void drawMidPoints(Canvas canvas) {
        mPaint.setStrokeWidth(POINTWIDTH);
        mPaint.setColor(Color.BLUE);
        for (Point point : mMidPoints) {
            canvas.drawPoint(point.x, point.y, mPaint);

        }
    }

    private void drawMidMidPoints(Canvas canvas) {
        mPaint.setStrokeWidth(POINTWIDTH);
        mPaint.setColor(Color.YELLOW);
        for (Point point : mMidMidPoints) {
            canvas.drawPoint(point.x, point.y, mPaint);

        }
    }

    private void drawAssistPoints(Canvas canvas) {
        mPaint.setStrokeWidth(POINTWIDTH);
        mPaint.setColor(Color.GRAY);
        for (Point point : mAssistPoints) {
            canvas.drawPoint(point.x, point.y, mPaint);

        }
    }

    private void drawBezierPath(Canvas canvas) {
        mPaint.setStrokeWidth(LINEWIDTH);
        mPaint.setColor(Color.BLACK);
        mPath.reset();
        mPath.moveTo(mPoints.get(0).x, mPoints.get(0).y);

        for (int i = 0; i < mPoints.size() - 1; i++) {
            if (i == 0) {
                // 第一条为二阶贝塞尔
                mPath.quadTo(mAssistPoints.get(i).x, mAssistPoints.get(i).y, mPoints.get(i + 1).x, mPoints.get(i + 1).y);
            } else//一直到最后一条之前，是三阶贝塞尔曲线
                if (i < mPoints.size() - 2) {
                    mPath.cubicTo(mAssistPoints.get(i * 2 - 1).x, mAssistPoints.get(i * 2 - 1).y,
                            mAssistPoints.get(i * 2).x, mAssistPoints.get(i * 2).y,
                            mPoints.get(i + 1).x, mPoints.get(i + 1).y);

                } else//最后一条也是二阶贝塞尔曲线
                    if (i == mPoints.size() - 2) {
                        mPath.quadTo(mAssistPoints.get(mAssistPoints.size() - 1).x, mAssistPoints.get(mAssistPoints.size() - 1).y, mPoints.get(i + 1).x, mPoints.get(i + 1).y);

                    }

        }
        canvas.drawPath(mPath, mPaint);
    }


    public int mScreenWidth = -1, mScreenHeigh = -1;


    private void getScreenParams() {
        getWindowHeigh(mContext);
        getWindowWidth(mContext);
    }


    public int getWindowWidth(Context context) {
        if (mScreenWidth <= 0) {
            WindowManager wm = (WindowManager) (context
                    .getSystemService(Context.WINDOW_SERVICE));
            DisplayMetrics dm = new DisplayMetrics();
            wm.getDefaultDisplay().getMetrics(dm);
            mScreenWidth = dm.widthPixels;
        }
        return mScreenWidth;
    }


    public int getWindowHeigh(Context context) {

        if (mScreenHeigh <= 0) {
            WindowManager wm = (WindowManager) (context
                    .getSystemService(Context.WINDOW_SERVICE));
            DisplayMetrics dm = new DisplayMetrics();
            wm.getDefaultDisplay().getMetrics(dm);
            mScreenHeigh = dm.heightPixels;
        }
        return mScreenHeigh;
    }
}
